package edu.cornell.cubooks.dao.impl;

import java.util.List;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import edu.cornell.cubooks.dao.BidDao;
import edu.cornell.cubooks.domain.Bid;
import edu.cornell.cubooks.domain.Posting;
import edu.cornell.cubooks.domain.User;

@Transactional
public class BidDaoImpl extends GenericDaoImpl<Bid, Integer> implements BidDao {

	/*
	 * (non-Javadoc)
	 * @see edu.cornell.cubooks.dao.BidDao#getBidsForPosting(edu.cornell.cubooks.domain.Posting)
	 */
	@SuppressWarnings("unchecked")
	@Transactional(readOnly = false)
	public Set<Bid> getBidsForPosting(Posting posting) {
		
		List<Bid> bids = sessionFactory.getCurrentSession()
			.createCriteria(domainClass)
			.add(Restrictions.eq("posting", posting))
			.addOrder(Order.desc("price"))
			.list();
		return toSet(bids);
	}
	
	/*
	 * (non-Javadoc)
	 * @see edu.cornell.cubooks.dao.BidDao#isPlacedBidGreaterthanCurrentBid(java.lang.Float, Posting posting)
	 */
	@Transactional(readOnly = true)
	public boolean isPlacedBidGreaterthanCurrentBid(Float placedbid, Posting posting) {
		Float currentbid = (Float) sessionFactory.getCurrentSession()
			.createCriteria(domainClass).setProjection(
				Projections.projectionList()
					.add(Projections.max("bid.price"))
			)
			.add(Restrictions.eq("bid.posting", posting))
			.uniqueResult();
		
		if (currentbid == null) {
			return true;
		}
		
		if(currentbid >= placedbid) {
			return false;
		}
		return true;
	}
	
	/*
	 * (non-Javadoc)
	 * @see edu.cornell.cubooks.dao.BidDao#getAllForGivenUser(edu.cornell.cubooks.domain.User)
	 */
	@SuppressWarnings("unchecked")
	@Transactional(readOnly = false)
	public Set<Bid> getAllForGivenUser(User user) {
		List<Bid> bids = (List<Bid>) sessionFactory.getCurrentSession()
			.createCriteria(domainClass)
			.add(Restrictions.eq("user", user))
			.list();
		
		return toSet(bids);
	}
	
	/*
	 * (non-Javadoc)
	 * @see edu.cornell.cubooks.dao.BidDao#placeBid(edu.cornell.cubooks.domain.Bid)
	 */
	@Transactional(readOnly = false) 
	public void placeBid(Bid bid) {
		Session currentSession = sessionFactory.getCurrentSession();
		currentSession.save(bid);
		currentSession.flush();
	}
}